<template>
	<div class="sroll-list-box">
		<div class="sroll-list-head" v-show="isShowCheckAll && options.length">
			<a-checkbox :disabled="allCheckBoxDisabled" :indeterminate="indeterminate" :checked="isCheckAll" @change="onCheckAllChange" >
				<span style="color:#000">{{ $i18n('selectPeople.all.selected') }}</span>
			</a-checkbox>
		</div>

		<div
			:class="['infinite-container', isShowCheckAll ? '' : 'infinite-container-max']"
			v-infinite-scroll="infiniteOnLoadHandle"
			:infinite-scroll-disabled="false"
			:infinite-scroll-distance="10"
		>
			<template v-if="model === 'single'">
				<singleItem
					v-for="item of options"
					:key="item.$_selectKey"
					:entityData="item"
					:checked="onSetSingleRadio(item)"
					:showCheckbox="showCheckbox"
					:showOtherProp="showOtherProp"
					:otherProps="otherProps"
					:model="model"
					:onRadioLabelToggle="onRadioLabelToggle"
					:onRadioToggle="onRadioToggle.bind(this,item)"
					:iconType="iconType"
					:currentId="currentId"
					:selectType="selectType"
				>
				</singleItem>
			</template>
			<template v-if="model === 'mult'">
				<div
					style="width: 100%"
					v-multi-select.clickNotClean="checked"
					@multi-select-change="multiSelectChange"
					v-if="singleAndMult"
				>
					<singleAndMultItem
						v-for="item of options"
						:key="item.$_selectKey"
						:entityData="item"
						:showCheckbox="showCheckbox"
						:showOtherProp="showOtherProp"
						:otherProps="otherProps"
						:model="model"
						:onPropToggle="onPropToggle"
						:data-select-key="item | toRightListKeyFilter"
						:data-select-disabled="item.$_isDisabled"
						:iconType="iconType"
						:currentId="currentId"
						:selectType="selectType"
					>
					</singleAndMultItem>
				</div>
				<div
					v-multi-select.clickNotClean="checked"
					@multi-select-change="multiSelectChange"
					v-if="!singleAndMult"
				>
					<!-- ref="listItem" -->
					<notSingleAndMultItem
						class='checkbox-item'
						v-for="item of options"
						:key="item.$_selectKey"
						:entityData="item"
						:showCheckbox="showCheckbox"
						:showOtherProp="showOtherProp"
						:otherProps="otherProps"
						:model="model"
						:onPropToggle="onPropToggle"
						:data-select-key="item | toRightListKeyFilter"
						:data-select-disabled="item.$_isDisabled"
						:iconType="iconType"
						:currentId="currentId"
						:selectType="selectType"
					>
					</notSingleAndMultItem>
				</div>
			</template>
			<div v-if="loading && !loadAll" class="loading-container">
				<a-spin/>
			</div>
		</div>
	</div>
</template>
<script>
import InfiniteScroll from '@/directive/InfiniteScroll';
import MultiSelect from '@/directive/MultiSelect';
import { getPanelData } from '@/api/modules/SelectOrgApi';
import { mapActions, mapState } from 'vuex';
import { ACTION_ADD_ENTITY, ACTION_REMOVE_ENTITY, ACTION_TOGGLE_ENTITY } from '@/store/actionTypes';
import { getSelectKey } from '@/utils/utils';
import { CheckUtils } from '@/utils/checkUtils';
import singleAndMultItem from './items/singleAndMultItem.js';
import notSingleAndMultItem from './items/notSingleAndMultItem.js';
import singleItem from './items/singleItem.js';

import { EntityTypes } from '@/utils/orgConstants';

export default {
	name: 'ScrollList',
	inject: ['app'],
	directives: { InfiniteScroll, MultiSelect },
	components: {
		singleAndMultItem,
		notSingleAndMultItem,
		singleItem
	},
	props: {
		panel: {
			/* 列表请求中的 panel */
			type: String,
			require: true
		},
		command: {
			/* 列表请求中的 command */
			type: String,
			require: true
		},
		showOtherProp: {
			/* 列表中是否展示其他属性 */
			type: Boolean,
			default: true
		},
		otherProps: {
			/* 其他属性字段 */
			type: Array,
			default: () => []
		},
		showCheckbox: {
			type: Boolean,
			default: true
		},
		searchProp: {
			type: Object,
			default: () => {
			}
		},
		firstLoadSearch: {
			/* 初次加载是否查询，外部页面需要控制这个值为true才会进行查询 */
			type: Boolean,
			default: true
		},
		initSearchValue: {
			type: Object,
			default: () => {
			}
		},
		titleProps: {
			/* hover 上去显示的内容  例如：该显示item.$_showLabel, 传值： label: 'label的中文内容' */
			type: Object,
			default: () => {
			}
		},
		singleAndMult: {
			/* 将复选框和文本选择事件分隔开 */
			type: Boolean,
			default: false
		},
		checkAllShow: {
			/* 在mult模式下是否展示全选按钮 */
			type: Boolean,
			default: true
		},
		disabledProp: {
			type: String,
			default: ''
		},
		isNotDisableProp: {
			/* disabled的属性的值的取反 */
			type: Boolean,
			default: true
		},
		checkBoxStrictly: {
			/* 分离复选框默认的选中事件， true 时复选框的选中状态完全受控*/
			type: Boolean,
			default: false
		},
		listDataHandler: {
			type: Function || null,
			default: null
		},
		departmentHandler: {
			type: Function || null,
			default: null
		},
		/** 自定义图标*/
		iconType: { type: String, default: '' }
	},
	data() {
		return {
			options: [],
			loading: false,
			loadAll: false,
			loadData: false,
			selectType: [],
			pageNo: 1,
			searchValue: '',
			checked: {},
			optionsMap: {},
			active: '',
			currentId: '',
			fixedStyle: {
				width: '430px'
			},

			isCheckAll: false,
			indeterminate: false,
			srollCheckedList: [],

			isLoadMoreDdata: this.firstLoadSearch
		};
	},
	computed: {
		pageSize() {
			const { defaultPageSize } = this.app().orgSelect;
			return defaultPageSize || 100;
		},
		model() {
			const { maxSize } = this.app().orgSelect;
			if (Number(maxSize) === 1) {
				return 'single';
			}
			return 'mult';
		},
		...mapState('selectData', {
			selectMap: (state) => {
				let selecteKeydMap = {};
				for (let item in state.selectedEntityMap) {
					if (state.selectedEntityMap[item].hasOwnProperty('$_selectKey')) {
						selecteKeydMap[state.selectedEntityMap[item].$_selectKey] = true;
					}
				}
				return selecteKeydMap;
			}
		}),
		activeTab() {
			return this.app().activeTab;
		},
		// 需要检查的 type 数组集合 检查范围：超出工作范围、超出工作职级范围、有无人员、超出人员范围
		checkConfigEnumsTypes() {
			let list = [];
			this.app().orgSelect.checkConfigEnums.forEach((el) => list.push(el.name));
			return list;
		},
		currentPanel() {
			return this.app().activeTab;
		},
		allCheckBoxDisabled() {
			let disabled = this.options.every(item => item.$_isDisabled === true );
			return disabled;
		},
		isShowCheckAll() {
			if (this.model !== 'single' && this.checkAllShow) {
				return true;
			} else {
				return false;
			}
		}
	},
	watch: {
		selectMap(val) {
			this.onSetCheckAllStatus(val);
		}
	},
	mounted() {
		let clientWidth = this.$el.clientWidth;
		this.fixedStyle = {
			width: clientWidth - 35 + 'px'
		};
		this.searchValue = this.initSearchValue;
		this.selectType = this.app().orgSelect.selectType;
	},
	methods: {
		...mapActions('selectData', [ACTION_ADD_ENTITY, ACTION_REMOVE_ENTITY,ACTION_TOGGLE_ENTITY]),
		setOptionsStatus(selectMap) {
			// 多选延迟修复
			if (this.model === 'mult') {
				let list = this.$el.querySelectorAll('.checkbox-item');
				const selectMapKeys = Object.keys(selectMap);
				if (list && list.length) {
					this.options.forEach((item,i)=>{
						if (!list[i]) {
							return;
						}
						let checked = selectMap[item.$_selectKey] || this.onSetMemberCheckboxStatus(selectMapKeys, item);

						let ele = list[i].querySelector('.ant-checkbox');
						if (!ele) {
							return;
						}
						let eleClassList = Array.from(ele.classList);
						let isDisabled = eleClassList.includes('ant-checkbox-disabled');
						let newClassList = ['ant-checkbox'];
						if (checked) {
							newClassList.push('ant-checkbox-checked');
						}
						if (isDisabled) {
							newClassList.push('ant-checkbox-disabled');
						}
						ele.setAttribute('class', newClassList.join(' '));
					});
				}
			}
		},
		search(value, orgParams) {
			this.initProps();
			this.searchValue = value;
			this.searchHandle({
				showConcurrentMember:this.app().orgSelect.showConcurrentMember,
				pageSize: this.pageSize,
				pageNo: this.pageNo,
				...this.searchValue
			}, orgParams);
		},
		initProps() {
			this.pageNo = 1;
			this.searchValue = {};
			this.options = [];
			this.optionsMap = {};
			this.loadAll = false;
			this.loadData = false;
			this.currentId = '';
			this.isCheckAll = false;
		},
		infiniteOnLoadHandle() {
			if (!this.isLoadMoreDdata) {
				return;
			}
			if (this.loadAll) {
				return;
			}
			if (this.loading) {
				return;
			}
			let config = {
				pageSize: this.pageSize,
				pageNo: this.pageNo
			};
			if (JSON.stringify(this.searchValue) !== '{}') {
				config = {
					showConcurrentMember:this.app().orgSelect.showConcurrentMember,
					pageSize: this.pageSize,
					pageNo: this.pageNo,
					...this.searchValue
				};
			}
			this.searchHandle(config);
		},
		/**
		 * @param {Object} config 是arguments所需参数
		 * @param {Object} orgParams 是与pannel同级参数
		 *
		*/
		async searchHandle(config, orgParams = {}) {
			if(this.selectType.includes('Mobile')){
				config.filterType = 'mobile';
			}else if(this.selectType.includes('Email')){
				config.filterType = 'email';
			}else{
				config.filterType = '';
			}
			if (this.loading) {
				return;
			}
			this.loading = true;
			let { code, data, message, cost } = await getPanelData({
				panel: this.panel,
				command: this.command,
				arguments: config,
				...orgParams,
			});
			this.loadData = true;
			// 返回仿真时间
			this.$emit('listSimulation', cost);
			if (String(code) !== '0') {
				this.$message.error(message);
				this.loading = false;
				return;
			}
			if (this.listDataHandler) {
				data = this.listDataHandler(data);
			}
			this.dataHandle(data);
		},
		dataHandle(data) {
			const _t = this;
			this.options = this.options.concat(
				data.map((item) => {
					if (!this.listDataHandler) {
						//item.$_selectKey = item.id;
						item.$_showLabel = item.name;
						item.$_selectKey = getSelectKey(item);
					}
					item.$_isDisabled = false;
					if (this.disabledProp) {
						if (this.isNotDisableProp) {
							item.$_isDisabled = !item[this.disabledProp];
						} else {
							item.$_isDisabled = item[this.disabledProp];
						}
					}
					if (!_t.selectType.includes(item.type)) {
						item.$_isDisabled = true;
					}
					/**
					 * 处理虚拟组织被选择，
					 */
					if (String(item.orgType) === '3') {
						item.$_isDisabled = true;
					}
					this.$set(this.optionsMap, item.$_selectKey, item);
					/** 人员处理hover提示 */
					if (item.type === EntityTypes.Member) {
						let resMember = this.onHandlerPartTimeMember(item);
						item = {...item, ...resMember};
					}
					// console.log('item===>', item);
					return item;
				})
			);
			this.isLoadMoreDdata = true;
			if (data.length < this.pageSize) {
				this.loadAll = true;
			}
			if (this.pageNo > 1 && this.isCheckAll) {
				this.indeterminate = true;
				this.isCheckAll = false;
			}
			this.pageNo++;
			this.loading = false;
			this.onSetCheckAllStatus(this.selectMap,'init');
		},
		onPropToggle(item) {
			if (this.singleAndMult) {
				this.currentId = item.$_selectKey;
				this.$emit('toCheckValueClickProp', item);
			}
		},
		onRadioToggle(item) {
			if (this.checkBoxStrictly) {
				this.$emit('tocheckBoxChange', item);
				this.$emit('checked', [item]);
			} else {
				if (item.$_isDisabled) {
					return;
				}
				this.onSelectToggleBefore([item]);
			}
		},
		onRadioLabelToggle(item) {
			if (this.singleAndMult) {
				this.currentId = item.$_selectKey;
				this.$emit('toCheckValueClickProp', item);
			} else {
				if (item.$_isDisabled) {
					return;
				}
				this.onSelectToggleBefore([item]);
			}
		},
		multiSelectChange(retValue) {
			const { detail } = retValue;
			const _t = this;
			const ret = [];
			detail.forEach((eachItem) => {
				let item = _t.optionsMap[eachItem];
				if (item.$_isDisabled) {
					return;
				}
				ret.push(item);
			});
			if (this.checkBoxStrictly) {
				this.$emit('tocheckBoxChange', ret);
				this.$emit('checked', ret);
			} else {
				this.onSelectToggleBefore(ret);
			}
		},
		/**
		 * 处理部门人员、岗位人员、职务级别人员兼职的展示处理
		 */
		onHandlerPartTimeMember(data) {
			let { sourceDepts, sourcePosts } = data;
			if (sourceDepts.length) {
				let deptList = [];
				sourceDepts.forEach((el) => {
					deptList.push(el.name);
				});
				data.deptFullName = deptList.join(',');
				data.deptName = deptList.join(',');
			}
			if (sourcePosts.length) {
				let postList = [];
				sourcePosts.forEach((el) => {
					postList.push(el.name);
				});
				data.postName = postList.join(',');
			}
			return data;
		},
		/**
		 * @params selectData { Array } 需要检测的数组
		 */
		async onSelectToggleBefore(selectData) {
			if (selectData.length === 0) {
				return;
			}
			let notIncludeSubDept = [];
			let checkContext = {
				currentPanel: this.currentPanel,
				notIncludeSubDept: notIncludeSubDept
			};
			// 兼容自定义选人处理不包含子部门
			for (let entity of selectData) {
				if (entity.$_excludeChildDepartment) {
					notIncludeSubDept.push(entity.id);
				}
			}
			// 单选
			if (this.model === 'single') {
				let result = await CheckUtils.doCheckEntity(selectData[0], checkContext);
				if (result) {
					this.selectDataToRight(selectData);
				}
				return;
			}
			// 部门
			if (selectData[0].type === EntityTypes.Department) {
				if (this.departmentHandler) {
					this.departmentHandler(selectData[0]);
					return;
				}
			}

			let checkedDatas = [];
			let toDelDatas = [];
			for (let entity of selectData) {
				if (this.selectMap[entity.$_selectKey]) {
					toDelDatas.push(entity);
				} else {
					let result = await CheckUtils.doCheckEntity(selectData[0], checkContext);
					if (result) {
						checkedDatas.push(entity);
					}
				}
			}
			if (checkedDatas.length) {
				this[ACTION_ADD_ENTITY]({ entities: checkedDatas, notIncludeSubDept: notIncludeSubDept });
			}
			if (toDelDatas.length) {
				this[ACTION_REMOVE_ENTITY]({ entities: toDelDatas, notIncludeSubDept: notIncludeSubDept  });
			}
		},
		onCheckAllChange(e) {
			let check = e.target.checked;
			let notIncludeSubDept = [];
			if (check) {
				const allDatas = this.options;
				let notDepth = allDatas;
				if (this.departmentHandler) {
					notDepth = [];
					for (const allDatasKey in allDatas) {
						const eachData = allDatas[allDatasKey];
						if (eachData.type === EntityTypes.Department) {
							this.departmentHandler(eachData);
						} else {
							notDepth.push(eachData);
						}
					}
				}
				// 全选时处理设置disabledProp
				if (this.disabledProp) {
					notDepth = [];
					for (const entity of allDatas) {
						if (!entity.$_isDisabled) {
							notDepth.push(entity);
						}
					}
				}
				// 兼容自定义选人处理不包含子部门
				for (let entity of notDepth) {
					if (entity.$_excludeChildDepartment) {
						notIncludeSubDept.push(entity.id);
					}
				}
				this[ACTION_ADD_ENTITY]({ entities: notDepth, notIncludeSubDept: notIncludeSubDept });
			} else {
				this[ACTION_REMOVE_ENTITY]({ entities: this.options });
			}
			this.indeterminate = false;
			this.isCheckAll = check;
		},
		/**
		 * 设置全选按钮checkbox状态
		*/
		onSetCheckAllStatus(selectMapData,mode) {
			if (mode == 'init') {
				this.$nextTick(()=>{
					this.setOptionsStatus(selectMapData);
				});
			} else {
				this.setOptionsStatus(selectMapData);
			}
			if (this.model !== 'single') {
				let selectedEntityKeys = Object.keys(selectMapData);
				if (selectedEntityKeys.length === 0) {
					this.isCheckAll = false;
					this.indeterminate = false;
					return;
				}
				let isCheckedAll = this.options.every(item => {
					return selectedEntityKeys.includes(item.$_selectKey) || this.onSetMemberCheckboxStatus(selectedEntityKeys, item);
				});
				let isCheckedSome = this.options.some(item => selectedEntityKeys.includes(item.$_selectKey));
				if (isCheckedAll) {
					this.indeterminate = false;
					this.isCheckAll = true;
					return;
				}
				if (isCheckedSome) {
					this.indeterminate = true;
				} else {
					this.indeterminate = false;
					this.isCheckAll = false;
				}
			}
		},
		/**
		 * 人员跨页签勾选处理
		 * @param {Array} selectMap 键数组
		 * @param {Object} entity 实体数据
		 * @return {Boolean} 是否勾选，默认false不勾选，true勾选
		 *
		*/
		onSetMemberCheckboxStatus(selectMapKeys, entity) {
			const { type, id } = entity;
			let checked = false;
			if (type === EntityTypes.Member) {
				let typeId = `${type}|${id}`;
				selectMapKeys.forEach(key => {
					if (key.includes(typeId)) {
						checked = true;
					}
				});
			}
			return checked;
		},
		/**
		 * 处理单选时人员勾选
		 * @param {Object} entity 实体数据
		*/
		onSetSingleRadio(entity) {
			const selectMapKeys = Object.keys(this.selectMap);
			const isCheck = this.selectMap[entity.$_selectKey] || this.onSetMemberCheckboxStatus(selectMapKeys, entity);
			return isCheck;
		}
	}
};
</script>

<style lang="scss" >

.sroll-list-box {
	height: 100%;
    box-sizing: border-box;
	.sroll-list-head {
		padding: 8px 10px 0 14px;
		box-sizing: border-box;
	}

}
.infinite-container {
	width: 100%;
	height: calc(100% - 31px);
    padding-bottom: 6px;
	box-sizing: border-box;
	background: #fff;
	user-select: none;
	overflow: auto;
	overflow-x: hidden;
    position: relative;

	&.infinite-container-max{
		height: 100%;
	}

	& /deep/ .ant-checkbox-group {
		display: block;
	}

	& /deep/ .ant-checkbox-wrapper {
		display: inline-block;
		margin: 0;
	}

	& /deep/ .ant-radio-group {
		display: block;
	}

	& /deep/ .ant-radio-wrapper {
		display: block;
		margin: 0;
	}


	.load-all {
		height: 40px;
		line-height: 20px;
		text-align: center;
		color: #999;
		font-size: 12px;
	}

	.loading-container {
		width: 100%;
		text-align: center;
	}

	.checkbox-item {
		width: 100%;
		height: 22px;
		box-sizing: border-box;
		padding-left: 14px;
		position: relative;
		margin-top: 4px;
		&.checkbox-item-active {
			background: $checkedColor;
		}
		& /deep/ .ant-checkbox + span {
			display: inline-block;
			width: calc(100% - 24px);
			@include ellipsis();
		}

		.checkbox-item-checkbox {
			align-items: inherit;
			overflow: hidden;
			float: left;
			height: 22px;
    		line-height: 22px;

			& /deep/ .ant-radio + span {
				display: inline-block;
				width: calc(100% - 24px);
				@include ellipsis();
				vertical-align: -6px;
			}

			& /deep/ .ant-checkbox {
				margin-top: 2px;
			}
		}


		.singleAndMult {
			flex: none;

			& + div {
				margin-left: 0;
			}
		}
		&:hover {
			background: $hoverColor;
		}

		& .tooltip-wrap {
			display: flex;
			width: calc(100% - 18px);
			align-items: center;
		}
	}

	.checkbox-item-disabled {
		cursor: not-allowed;

		.other-prop {
			cursor: not-allowed;
		}
	}

	.btn-box {
		position: fixed;
		z-index: 1;
		width: 430px;
		display: flex;
		align-items: center;
		padding: 6px 0 6px 14px;
		background: #fff;

		.btn {
			display: flex;
			justify-content: center;
			align-items: center;
			font-size: 14px;
			color: #333;
			outline: none;
			border: 1px solid $borderColor;
			background: #fff;
			cursor: pointer;

			&:hover {
				color: $commonBlue;
				border-color: $commonBlue;
			}

			&:first-child {
				margin-right: 10px;
			}
		}

		.active-btn {
			color: $commonBlue;
			border-color: $commonBlue;
		}
	}

	.btn-box-shadow {
		width: 100%;
		height: 36px;
	}
}
</style>
